package com.project.serviceImpl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.ftp.Ftp;
import com.project.service.FtpService;
import com.project.utils.FtpDownLoadUtils;
import com.project.utils.file.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;

/**
 * @author : Mr.Yan
 * @program : com.project.serviceImpl
 * @create : 2020/07/13
 * @description : ftp 服务实现层
 */
@Slf4j
@Service
@Transactional
public class FtpServiceServiceImpl implements FtpService {

    @Override
    public Ftp ftpLogin(String host, int port, String user, String password) {
        try {
            Ftp ftp = new Ftp(host, port, user, password);
            FTPClient client = ftp.getClient();
            if (!FTPReply.isPositiveCompletion(client.getReplyCode())) {
                client.disconnect();
                this.ftpClose(ftp);
                log.error("未连接到FTP，用户名或密码错误。");
            } else {
                log.info("FTP connection success");
                return ftp;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public FTPFile[] ftplsFiles(Ftp ftp, String remoteFolder) {
        ftp.cd(remoteFolder);
        FTPFile[] ftpFiles = ftp.lsFiles(remoteFolder);
        return ftpFiles;
    }

    @Override
    public String newFolder(Ftp ftp, String folderName, String folderPath) {
        boolean cd = ftp.cd(folderPath);
        if (cd) {
            FTPFile[] ftpFiles = this.ftplsFiles(ftp, folderPath);
            for (FTPFile ftpFile : ftpFiles) { // 循环文件
                // 需要加此判断。否则，ftp默认将‘项目文件所在目录之下的目录（./）’与‘项目文件所在目录向上一级目录下的目录（../）’都纳入递归，这样下去就陷入一个死循环了。需将其过滤掉。
                if (!".".equals(ftpFile.getName()) && !"..".equals(ftpFile.getName())) {
                    if (ftpFile.getName().equals(folderName)) {
                        folderName = String.format("%s-%s-%s", folderName, DateUtil.format(new Date(), "yyyyMMdd"), String.valueOf(System.currentTimeMillis()));
                        break;
                    }
                }
            }
            boolean mkdir = ftp.mkdir(folderName);
            if (mkdir) {
                log.info(String.format("创建文件夹'%s'成功", folderName));
                return folderName;
            } else {
                log.error(String.format("创建文件夹'%s'失败", folderName));
            }
        } else {
            log.error(String.format("进入根目录'%s'失败", folderPath));
        }
        return "";
    }

    @Override
    public boolean deleteFile(Ftp ftp, String name, String folderPath) {
        ftp.cd(folderPath);
        boolean delFile = ftp.delFile(String.format("%s/%s", folderPath, name));
        return delFile;
    }

    @Override
    public boolean deleteDir(Ftp ftp, String name, String folderPath) {
        ftp.cd(folderPath);
        boolean delDir = ftp.delDir(String.format("%s/%s", folderPath, name));
        return delDir;
    }

    @Override
    public void ftpClose(Ftp ftp) {
        try {
            ftp.close();
            log.info("ftp关闭连接成功");
        } catch (IOException e) {
            log.error("ftp关闭连接成失败");
            e.printStackTrace();
        }
    }

    @Override
    public boolean rename(Ftp ftp,String srcName, String toName, String folderPath) {
        boolean cd = ftp.cd(folderPath);
        if (cd) {
            FTPClient client = ftp.getClient();
            try {
                boolean rename = client.rename(srcName, toName);
                return rename;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    @Override
    public void downloadFile(Ftp ftp, String name, String folderPath, HttpServletRequest request) {
        try {
            ftp.cd(folderPath);
            new FtpDownLoadUtils().download(ftp.getClient(),folderPath, name, request);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String updateFile(Ftp ftp, MultipartFile chooseFile, String folderPath) {
        ftp.cd(folderPath);
        String fileName = chooseFile.getOriginalFilename();
        FTPFile[] ftpFiles = this.ftplsFiles(ftp, folderPath);
        for (FTPFile ftpFile : ftpFiles) { // 循环文件
            // 需要加此判断。否则，ftp默认将‘项目文件所在目录之下的目录（./）’与‘项目文件所在目录向上一级目录下的目录（../）’都纳入递归，这样下去就陷入一个死循环了。需将其过滤掉。
            if (!".".equals(ftpFile.getName()) && !"..".equals(ftpFile.getName())) {
                if (ftpFile.getName().equals(fileName)) {
                    String prefix = FileUtil.getExtensionName(fileName);
                    fileName = String.format("%s-%s-%s.%s", StrUtil.sub(fileName, 0 , ((prefix.length() + 1) * -1 )), DateUtil.format(new Date(), "yyyyMMdd"), String.valueOf(System.currentTimeMillis()), prefix);
                    break;
                }
            }
        }
        boolean upload = ftp.upload(folderPath, fileName, FileUtil.toFile(chooseFile));
        if (upload) {
            return fileName;
        }
        return "";
    }
}
